package gu;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.jsoup.nodes.DataNode;

public class checkLink9{
	public static final String HTTP = "http://";
	public static final String LOGIN_NONE = "1", LOGIN_FORM = "2", LOGIN_PROCESS = "3";
	// web page extension to extract URL from JavaScript
	public static String  pageExt= "do,jsp";//,asp,aspx,php";//  
	
	private String targetDomain="", virtualDirectory="";
	private String startURL = "";
	private String LoginURL = "";
	private String LoginInfo = "", formID="";
	private String exceptURL = "";
	// list of extract url 
	public HashMap<String , linkInfo9> urlList = new HashMap<String , linkInfo9>();
	private HttpManager httpManager;
	private progressEvent9 foundEvent;
	
	public static void main(String[] args) throws IOException {
		
		checkLink9 cl = new checkLink9();
		cl.executeCheck(LOGIN_FORM);
		
		int cnt=0;
        for( String key : cl.urlList.keySet() ){
        	linkInfo9 li = cl.urlList.get(key);
        	if (li==null) continue;
            System.out.println( String.format("%s(%s): responseCode: %s, download time: %sms", key, li.getTitle(), li.getResponseCode(), li.getResponseTime() ) );
    		cnt ++;
        }
        
		System.out.println("done : " + cnt);
	}
	
	public void executeCheck(String loginType){
		init();
		
		if (LOGIN_FORM.equals(loginType))
			 httpManager = new HttpManager4Form();
		else httpManager = new HttpManager4Process();
	    
		if (!LOGIN_NONE.equals(loginType) & !"".equals(LoginURL.replace(HTTP, ""))) 
			httpManager.Login(LoginURL, LoginInfo, formID);
		
		try {
			chk_document( startURL);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		if (foundEvent!=null) foundEvent.endFindDocuemnt();
		
		httpManager = null;
	}
	
	public void init() {
		pageExt = pageExt.replace(",", "|");
		pageExt = pageExt.replace(" ", "");

		try {
			URL url = new URL(targetDomain);
			virtualDirectory=url.getPath();
			virtualDirectory = virtualDirectory.replace("/", "");
			
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
		
	}	
	
	public void chk_document(String url) throws IOException {
		if (urlList.containsKey(url)) if (urlList.get(url)!=null) return; // already check
		
		linkInfo9 li = new linkInfo9();
		String targetURL = extractUrlPath(url);
		//System.out.println(url);
		Document doc = httpManager.GetDocument(targetDomain + targetURL);
		
		li.setResponseCode(httpManager.responseCode);
		li.setResponseTime(httpManager.responseTime);
		if (doc!=null) li.setTitle(doc.title());
		urlList.put(targetURL, li);

		if (foundEvent!=null) foundEvent.findDocuemnt(targetURL, li);
		
		if (doc==null) return;
		
		ArrayList<String> url_arr = new ArrayList<String>();
		
		// extranct HTML link(href) 
		Elements links = doc.select("a[href]");
		for(Element l: links){
			targetURL = l.attr("abs:href");
			if ("".equals(targetURL)) targetURL = l.attr("href");
			if (targetURL.indexOf("#")==-1)
				url_arr.add(extractUrlPath(targetURL));
		}
		links = null;
		
		// extranct link in javascript 
		Elements scriptElements = doc.getElementsByTag("script");
		for (Element element :scriptElements ){                
			for (DataNode node : element.dataNodes()) {
				get_URLfromScript(node.getWholeData(), pageExt, url_arr);
			}
		}
		doc = null;
		scriptElements = null;
		
		for (int i=0; i<url_arr.size(); i++) {
			targetURL = url_arr.get(i).trim(); 
			if (addURL(targetURL)){
				chk_document (targetURL);
			}	
		}	
	}
	
	public boolean chkEnd()  {
        for( String key : urlList.keySet() ){
        	if (urlList.get(key)==null) return false;
        }
    	return true;
	}
	
	public boolean addURL(String targetURL)  {
		if ("".equals(targetURL) || urlList.containsKey(targetURL)) return false;

		boolean chk = exceptURL.indexOf(targetURL)==-1;
		if (chk) urlList.put(targetURL, null);
		return chk;
	}
	/*===============================================================================
	 * 
	 */
	// extract url from JavaScript code 
	
	public void get_URLfromScript(String script, String ext, ArrayList<String> url_arr)  {
		if ("".equals(ext)) return;
    	Pattern p = Pattern.compile("(?i)([\"|'])([-a-zA-Z0-9+&@#/%?=~_|!:,.;])*\\.(" + ext + ")([-a-zA-Z0-9+&@#/%?=~_|!:,.;])*([\"|'])");
    	Matcher m = p.matcher(script); 

    	while( m.find() ){
    		String st = m.group().substring(1);
    		st = st.replaceAll("[\"']+(.+?)", ""); 
    		st = extractUrlPath(st.substring(0,st.length()-1));
    	    url_arr.add(st);
    	    //System.out.println(st);
    	}		
	}

	/*====================================
	 * etc 
	 *  full url : domain + path + file
	 */
	public String extractUrlPath(String targetURL) {			
		if ("".equals(targetURL) || "#".equals(targetURL) || targetURL.indexOf("(")>-1 ) return "";
		String a = targetURL.toLowerCase();
		if ( a.indexOf("javascript:")>-1 || a.indexOf("mailto:")>-1 ) return "";

		String domain = ExtractDomain(targetURL);

		if ("".equals(domain)) { 								// short url : path + file
			if (targetURL.charAt(0) == '/') targetURL = targetURL.substring(1);
			if (!"".equals(virtualDirectory) & targetURL.indexOf(virtualDirectory)==0) targetURL = targetURL.replaceAll(virtualDirectory+"[/]", "");
		}else
		if (targetURL.indexOf(targetDomain)==-1) return "";		// other domain
	
		if (targetURL.indexOf("?")>-1) targetURL=targetURL.substring(0, targetURL.indexOf("?")); // one time if board
		
		return targetURL.replace(targetDomain, "");
	}
	
	public static String ExtractDomain(String targetURL){
		if ("".equals(targetURL) ) return "";

		URL url = null;
		try {
			url = new URL(targetURL);
		} catch (MalformedURLException e) {
			return "";
		}
		
		return url.getHost();
	}
	/* ================================================================ */
	public String getTargetDomain() {
		return targetDomain;
	}

	public void setTargetDomain(String targetDomain) {
		if (targetDomain.charAt(targetDomain.length()-1)!='/') targetDomain=targetDomain+'/';
		this.targetDomain = targetDomain;
	}

	public String getStartURL() {
		return startURL;
	}

	public void setStartURL(String startURL) {
		this.startURL = startURL;
	}

	public String getLoginURL() {
		return LoginURL;
	}

	public void setLoginURL(String loginURL) {
		LoginURL = loginURL;
	}

	public String getLoginInfo() {
		return LoginInfo;
	}

	public void setLoginInfo(String loginInfo) {
		LoginInfo = loginInfo;
	}

	public String getFormID() {
		return formID;
	}

	public void setFormID(String formID) {
		this.formID = formID;
	}

	public String getExceptURL() {
		return exceptURL;
	}

	public void setExceptURL(String exceptURL) {
		this.exceptURL = exceptURL;
	}

	public String getPageExt() {
		return pageExt;
	}

	public void setPageExt(String pageExt) {
		checkLink9.pageExt = pageExt;
	}

	public HashMap<String, linkInfo9> getUrlList() {
		return urlList;
	}

	public void setUrlList(HashMap<String, linkInfo9> urlList) {
		this.urlList = urlList;
	}

	public progressEvent9 getFoundEvent() {
		return foundEvent;
	}

	public void setFoundEvent(progressEvent9 foundEvent) {
		this.foundEvent = foundEvent;
	}

	
} 
